﻿package net.wangit.etl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import net.wangit.context.ActionContext;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.executable.SQLUtil;
import net.wangit.util.ArrayUtil;
import net.wangit.util.Checker;
import net.wangit.util.FileUtil;
import net.wangit.util.XMLUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;


public class Loader {

	private static final Log log = LogFactory
			.getLog(net.wangit.etl.Loader.class);

	public Loader() {
	}

	public static LoadResult load(DB db, String path) throws Exception {
		return load(db, path, null);
	}

	public static LoadResult load(DB db, String path, ActionContext ac)
			throws Exception {
		path = FileUtil.formatPath(path);
		String[] fileNames = null;
		File file = new File(path);
		if (file.isFile()) {
			int index = path.lastIndexOf("/");
			fileNames = (new String[] { path.substring(index + 1) });
			path = path.substring(0, index + 1);
		} else {
			path = FileUtil
					.formatPath((new StringBuilder(String.valueOf(path)))
							.append("/").toString());
			fileNames = FileUtil.listFiles(path);
		}
		if (fileNames == null)
			return new LoadResult(new String[0], new String[0], new int[0]);
		if (log.isDebugEnabled()) {
			log.debug((new StringBuilder("path=")).append(path).toString());
			ArrayUtil.print(fileNames);
		}
		int length = fileNames.length;
		String[] tableNames = new String[length];
		int[] counts = new int[length];
		for (int i = 0; i < fileNames.length; i++) {
			Document document = XMLUtil.parseByPath((new StringBuilder(String
					.valueOf(path))).append(fileNames[i]).toString());
			Element table = document.getRootElement();
			if (ac == null)
				tableNames[i] = table.attributeValue("name");
			else
				tableNames[i] = ac.getRequestParameter("");
			counts[i] = load(db, tableNames[i], table, ac);
		}

		return new LoadResult(fileNames, tableNames, counts);
	}

	private static int load(DB db, String tableName, Element table,
			ActionContext ac) throws Exception {
		List columnList = new ArrayList();
		List typeList = new ArrayList();
		List mappingList = new ArrayList();
		List columns = table.element("columns").elements("column");
		for (int i = 0; i < columns.size(); i++) {
			Element column = (Element) columns.get(i);
			String columnName = column.attributeValue("name");
			if (ac == null || Checker.isEmpty(ac.getRequestParameter(""))) {
				columnList.add(ac != null ? ((Object) (ac
						.getRequestParameter(""))) : ((Object) (columnName)));
				String type = ac != null ? ac.getRequestParameter("") : column
						.attributeValue("type");
				typeList.add(new Integer(type));
				mappingList.add(new Integer(i));
			}
		}

		List rows = table.element("rows").elements("row");
		return load(db, tableName, rows, ArrayUtil.toStringArray(columnList),
				ArrayUtil.toIntArray(typeList), ArrayUtil
						.toIntArray(mappingList));
	}

	private static int load(DB db, String tableName, List rows,
			String[] columns, int[] types, int[] mapping) throws Exception {
		String sql = SQLUtil.toInsertStatement(tableName, columns);
		for (int i = 0; i < rows.size(); i++) {
			Element row = (Element) rows.get(i);
			db.execute(sql, getValues(row, mapping), types);
		}

		return rows.size();
	}

	private static String[] getValues(Element row, int[] mapping) {
		List list = row.elements("value");
		String values[] = new String[mapping.length];
		for (int i = 0; i < mapping.length; i++) {
			Element node = (Element) list.get(mapping[i]);
			values[i] = ETLUtil.toDBValue(node.getText());
		}

		return values;
	}

}
